package com.gaoxizhe.ccc.util;

import com.sun.mail.util.MailSSLSocketFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.event.TransportEvent;
import javax.mail.event.TransportListener;
import javax.mail.internet.*;
import java.io.File;
import java.util.List;
import java.util.Properties;

@Slf4j
@Component
public class MailUtil {

    private enum DeliveredState {
        INITIAL, MESSAGE_DELIVERED, MESSAGE_NOT_DELIVERED, MESSAGE_PARTIALLY_DELIVERED;
    }

    private static class DeliveredStateFuture {
        private DeliveredState state = DeliveredState.INITIAL;
        synchronized void waitForReady() throws InterruptedException {
            if (state == DeliveredState.INITIAL) {
                wait();
            }
        }
        synchronized DeliveredState getState() {
            return state;
        }
        synchronized void setState(DeliveredState newState) {
            state = newState;
            notifyAll();
        }
    }

    private static String host; //smtp服务器

    private static String from; //发件人地址

    private static String user; //用户名

    private static String pwd; //授权码

    @Value("${mail.host}")
    public void setHost(String host) {
        this.host = host;
    }

    @Value("${mail.from}")
    public void setFrom(String from) {
        this.from = from;
    }

    @Value("${mail.user}")
    public void setUser(String user) {
        this.user = user;
    }

    @Value("${mail.pwd}")
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    //防止附件名过长问题
    static {
        System.setProperty("mail.mime.splitlongparameters", "false");
        System.setProperty("mail.mime.charset", "UTF-8");
    }

    /**
     * 发送邮件
     * @param subject 主题
     * @param content 内容
     * @param recipientsList 收件人
     * @param fileName 文件名
     * @param attachmentList 附件
     * @param ccList 抄送人
     */
    public static void sendeMail(String subject, String content, List<String> recipientsList,
                                 String fileName, List<File> attachmentList, String ccList) {
        log.info("开始发送邮件");
        Properties props = new Properties();

        if (host == null || "".equals(host)) {
            host = "smtp.163.com";
        }
        if (from == null || "".equals(from)) {
            from = "15313861701@163.com";
        }
        if (user == null || "".equals(user)) {
            user = "15313861701@163.com";
        }
        if (pwd == null || "".equals(pwd)) {
            pwd = "lm1701";
        }

        props.put("mail.smtp.host", host); //设置发送邮件的邮件服务器的属性
        //发送邮件协议名称
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.auth", "true"); //需要经过授权，也就是有户名和密码的校验，这样才能通过验证（一定要有这一条）
//        props.put("mail.smtp.port", 25);
        Transport transport = null;
        DeliveredStateFuture future = new DeliveredStateFuture();
        try {
            //SSL加密
            MailSSLSocketFactory msf = new MailSSLSocketFactory();
            //设置信任所有的主机
            msf.setTrustAllHosts(true);
            props.put("mail.smtp.ssl.enable", "true");
            props.put("mail.smtp.ssl.socketFactory", msf);
            //用props对象构建一个session
            Session session = Session.getDefaultInstance(props);
            session.setDebug(false);
            MimeMessage message = new MimeMessage(session); //用session为参数定义消息对象

            //指定发送人
            message.setFrom(new InternetAddress(from)); //加载发件人地址

            //指定多个接收人
            InternetAddress[] toList = new InternetAddress[recipientsList.size()];
            for (int i = 0; i < toList.length; i++) {
                toList[i] = new InternetAddress(recipientsList.get(i));
            }
            message.setRecipients(Message.RecipientType.TO, toList);

            //指定抄送人
            if (ccList != null && !"".equals(ccList)) {
                message.addRecipients(Message.RecipientType.CC, ccList);
            }

            //message.addRecipients(MimeMessage.RecipientType.CC, InternetAddress.parse(FROM)); //设置在发送给收信人之前给自己（发送方）抄送一份，不然会被当成垃圾邮件，报554错
            message.setSubject(subject); //加载标题
            Multipart multipart = new MimeMultipart(); //向multipart对象中添加邮件的各个部分内容，包括文本内容和附件
            MimeBodyPart mimeBodyPart = new MimeBodyPart(); //设置邮件的文本内容
            mimeBodyPart.setContent(content, "text/html;charset=UTF-8");
            multipart.addBodyPart(mimeBodyPart, 0);
            //邮件附件，支持多个附件发送
            if (attachmentList != null && !attachmentList.isEmpty()) {
                for(File attachment : attachmentList) {
                    MimeBodyPart attachmentPart = new MimeBodyPart();
                    DataSource source = new FileDataSource(attachment);
                    attachmentPart.setDataHandler(new DataHandler(source));
                    //避免中文乱码的处理
                    attachmentPart.setFileName(MimeUtility.encodeWord(attachment.getName()));
                    multipart.addBodyPart(attachmentPart);
                }
            }

            message.setContent(multipart, "text/html;charset=UTF-8"); //将multipart对象放到message中
            message.saveChanges(); //保存邮件
            transport = session.getTransport(); //发送邮件

            //邮件传输监听器
            transport.addTransportListener(new TransportListener() {
                @Override
                public void messageDelivered(TransportEvent arg0) {
                    future.setState(DeliveredState.MESSAGE_DELIVERED);
                }

                @Override
                public void messageNotDelivered(TransportEvent arg0) {
                    future.setState(DeliveredState.MESSAGE_NOT_DELIVERED);
                }

                @Override
                public void messagePartiallyDelivered(TransportEvent arg0) {
                    future.setState(DeliveredState.MESSAGE_PARTIALLY_DELIVERED);
                }
            });

            transport.connect(host, user, pwd); //连接服务器的邮箱
            transport.sendMessage(message, message.getAllRecipients()); //把邮件发送出去
            transport.close(); //关闭连接Properties

            log.info("邮件传输监听器结果为：" + future.getState().toString());
            log.info("邮件发送成功");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            log.info("邮件传输监听器结果为：" + future.getState().toString());
            String stackTrace = ExceptionUtils.getStackTrace(e);
            log.info("邮件发送失败：" + stackTrace);
        } finally {
            if (transport != null) {
                try {
                    transport.close();
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                    String stackTrace = ExceptionUtils.getStackTrace(e);
                    log.info("关闭连接失败：" + stackTrace);
                }
            }
        }
    }

    /*public static void main(String[] args) {
        List<File> attachments = new ArrayList<>();
        File file1 = new File("C:\\Users\\pactera\\Desktop\\学生—作业的试卷.txt");
        File file2 = new File("D:\\图片\\java1.jpg");
        attachments.add(file1);
        attachments.add(file2);

        List<String> recipients = new ArrayList<>();
        recipients.add("15313861701@163.com");
        recipients.add("1044844347@qq.com");

        String ccList = "2309797702@qq.com";

        sendeMail("发送邮件测试", new Date() + "，发送成功", recipients, null, attachments, ccList);
    }*/

}
